
#ifndef _DECODER_SESSION_H_
#define _DECODER_SESSION_H_

#include <platform.h>
#include <uapi/stdio.h>
#include <system/sysbuf.h>
#include "session_global.h"
#ifdef CONFIG_MEDIA_EMULATE_ON_PC
#include <uapi/stdlib.h>
#include <uapi/memory.h>
#include <uapi/string.h>
#include <uapi/strings.h>
#include <uapi/time.h>
#include <uapi/timex.h>
#else
#include <system/sysmap.h>
#include <uapi/apps/color.h>

#include <fftype.h>
#include <utp/client/UtpClient.h>
#endif

//////////////////////////////////////////////////////////////////////////////////////////////
//

#define BASIC_PAGE_SIZE 4096

#define TS_PKTLEN	188

#ifndef CONFIG_MEDIA_EMULATE_ON_PC
#define XA_USE_EDMA_IOBUF
#endif
#define EDMA_CHN_IO 2
#define EDMA_CHN_MEDIA 3

//////////////////////////////////////////////////////////////////////////////////////////////
/**
*  debug
*/
#undef debug
#ifdef CONFIG_USR_SOC_APP_DEBUG
#define debug printf
#else
#define debug null_debug
#endif

//////////////////////////////////////////////////////////////////////////////////////////////

typedef enum
{
	SST_NONE,

	// SYSTEM
	SST_SYS,
	SST_NETFS,

	// DEVICES
	SST_DISPLAY,
	SST_USB,
	SST_I2SOUT,
	SST_I2SIN,

	// LCDI decoder
	SST_LCDI_JPEG,
	SST_LCDI_JPEG_DWJ,

	// VIDEO decoder
	SST_JPEG,
	SST_H264,
	SST_HEVC,
	SST_MPG2,
	SST_MPG4,
	SST_RV,
	SST_VC1,
	SST_VP8,

	// Audio decoder
	SST_WAV,

	SST_AAC,
	SST_AAC_ADIF,
	SST_AAC_ADTS,
	SST_AAC_LOAS,
	SST_AAC_LATM,

	SST_MP3,

	// Mixture decoder
	SST_TS,
	SST_MP4,
	SST_MKV,

	// END
	SST_TYPES,

}session_type_t;

typedef struct
{
	int type;
	int id;
#ifdef CONFIG_MEDIA_EMULATE_ON_PC
	int width;
	int height;
#endif
}session_video_type_t;

typedef struct
{
	int type;
	int id;
	int channel;
	int sample_rate;
	int sample_size;
	int bit_rate;
}session_audio_type_t;

#ifdef MEDIA_AV_SYNC
typedef struct
{
	int va_diff;				// units:ms, diff time of video - audio
	float v_pkt_duration;		// units: ms, estimated duration time per video packet, normally 40(ms)/25fps
	float a_pkt_duration;		// units: ms, estimated duration time per audio packet, normally 20~30ms
	uint64_t v_cur_pkt_dts;		// units:(1 / time_scale second), current video packet dts(Decoding Time Stamp)
	uint64_t v_cur_pkt_pts1;	// units:(1 / time_scale second), current video packet pts(Presentation Time Stamp)
	uint64_t v_cur_pkt_pts2;
	uint64_t a_cur_pkt_dts; 	// units:(1 / time_scale second), dts of currunt audio packet put to xa decoder
	uint64_t a_cur_pkt_pts; 	// units:(1 / time_scale second), pts of currunt audio packet will play
	int v_dts_time_base; 		// time_scale if mdhd box, v_cur_pkt_dts / v_dts_time_base = second
	int a_dts_time_base; 		// time_scale if mdhd box, a_cur_pkt_dts / a_dts_time_base = second
	float v_last_decode_time;	// units:(1 / time_scale second), used for calc pts from dts
	float a_last_decode_time;	// not use
	uint32_t v_cur_pkt_num;		// video packet number play current
	uint32_t a_cur_pkt_num;		// audio packet number play current
	uint32_t lace_total_num;	// for mkv
	media_time_t v_last_play_timestamp;		// video last frame display timestamp
	media_time_t a_play_buf_flush_timestamp;// audio last frame to play buffer timestamp
	int32_t a_play_buf_remaining_time;  	// units: ms, time of remaining buffer in i2sout
	int a_real_rate;			// units: Hz, the real audio play speed
	float v_real_duration;		// units: ms, the real video packet duration take audio real speed as the standard
	uint32_t skip_flag;			// 0x1 if audio skip start, 0x2 if video skip start, 0 skip end
	int speed;					// speed: x1 x2 x4 x8 x16
	media_time_t sys_time;		// system time, flushed by cyclical SessionRun()
}session_av_sync;
#endif

typedef struct
{
	int type;
	session_video_type_t tv;
	session_audio_type_t ta;
}session_netfile_t;

typedef enum
{
	STORAGE_TYPE_USB0,
	STORAGE_TYPE_USB1,
	STORAGE_TYPE_NETFS,
}storage_type_t;

typedef struct
{
	void *filename;
	int type;
	session_video_type_t tv;
	session_audio_type_t ta;
	storage_type_t ftype;
#ifdef MEDIA_AV_SYNC
	session_av_sync *sync;
#endif
}session_file_t;

//////////////////////////////////////////////////////////////////////////////////////////////
typedef void *SESSIONHANDLE;

typedef enum
{
	SSTATE_NULL = 0,
	SSTATE_INITED,
	SSTATE_RUNNING,
	SSTATE_RUNNING_IDLE,
	SSTATE_RUNNING_PAUSE,
	SSTATE_STOP,
}SESSIONSTATE;

typedef struct
{
	slists_t list;
	psysbuf_t buf;
}session_buffer_t;

struct SESSION
{
	const char name[128];
	const long types;

	SESSIONHANDLE(*SessionInit)(struct SESSION *session);

	SESSIONSTATE state;
	SESSIONHANDLE handle;
	SESSIONSTATE(*SessionRun)(struct SESSION *session);
	int(*SessionCommand)(struct SESSION *session, int cmd, void *params);
	void(*SessionDeInit)(struct SESSION *session);

	slists_group_t buffer_group;
};

#define SESSIONAPI(function) session_private##function

//session command lists
#include "session_cmd.h"

//session apis
#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

	///////////////////////////////////////////////////////
	// Debug
	extern int null_debug(const char *fmt, ...);

	///////////////////////////////////////////////////////
	// Sessions
	extern struct SESSION *SessionGet(session_type_t type);
	extern struct SESSION *SessionNext(struct SESSION *session);

	extern void SessionInitAll(const struct SESSION *gSessions_all[]);

	extern void SessionDeInitAll(void);

	extern void SessionBufferInit(struct SESSION *session);

	extern session_buffer_t *SessionBufferPush(struct SESSION *session, psysbuf_t buf);

	extern psysbuf_t SessionBufferPop(struct SESSION *session);
	extern psysbuf_t SessionBufferTop(struct SESSION *session);
	extern int SessionBufferTopNum(struct SESSION *session);

	extern void SessionBufferDeInit(struct SESSION *session);

	extern SESSIONSTATE SessionRun(struct SESSION *session);

	extern int SessionCommand(struct SESSION *session, int cmd, void *params);

#ifdef __cplusplus
}
#endif  /* __cplusplus */
#endif //_DECODER_SESSION_H_
